/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager.validate;

import com.inspur.edp.bcc.biztag.api.BizTagService;
import com.inspur.edp.bcc.biztag.entity.BizTag;
import com.inspur.edp.bef.bemanager.befexception.BeManagerException;
import com.inspur.edp.bef.bemanager.service.BeManagerService;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bemanager.util.ExpressionVariableCheckUtil;
import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.LogicDeleteControlInfo;
import com.inspur.edp.bef.bizentity.beenum.BETriggerTimePointType;
import com.inspur.edp.bef.bizentity.beenum.RequestNodeTriggerType;
import com.inspur.edp.bef.bizentity.operation.collection.TccSettingCollection;
import com.inspur.edp.bef.bizentity.operation.componentbase.BizReturnValue;
import com.inspur.edp.bef.bizentity.operation.componentenum.BizParameterType;
import com.inspur.edp.bef.bizentity.operation.componentinterface.IBizParameter;
import com.inspur.edp.bef.bizentity.operation.internalbeaction.IInternalBEAction;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.IInternalMgrAction;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.TccSettingElement;
import com.inspur.edp.bef.component.ICompParameter;
import com.inspur.edp.bef.component.ICompParameterCollection;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonValCollection;
import com.inspur.edp.cef.designtime.api.collection.DtmElementCollection;
import com.inspur.edp.cef.designtime.api.collection.ValElementCollection;
import com.inspur.edp.cef.designtime.api.element.*;
import com.inspur.edp.cef.designtime.api.operation.CommonOperation;
import com.inspur.edp.cef.designtime.api.operation.CommonValidation;
import com.inspur.edp.cef.designtime.api.validate.common.CheckUtil;
import com.inspur.edp.cef.designtime.api.variable.CommonVariableCollection;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.IObjectCollection;
import com.inspur.edp.das.commonmodel.entity.GspCommonModel;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.databaseobject.api.context.DatabaseReservedWords;
import io.iec.edp.caf.databaseobject.api.entity.DatabaseObjectColumn;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.springframework.util.StringUtils;

public class BizEntityValidater {

  private static final String BE_VALIDATOR_EXCEPTION = "BizEntityValidator";

  private static final String MODEL = "业务实体 '{%1$s}' ";
  private static final String OBJECT = "业务实体 '{%1$s}' 中节点 '{%2$s}' ";
  private static final String FIELD = "业务实体 '{%1$s}' 中节点 '{%2$s}' 的字段 '{%3$s}' ";
  private static final String VARIABLE = "业务实体 '{%1$s}' 中'变量集合' 的字段 '{%3$s}' ";
  private static final String VARIABLE_DTM = "业务实体 '{%1$s}' 中'变量集合' 的事件";
  private static final String OPT_BIZACTION = "业务实体 '{%1$s}' 中节点 '{%2$s}' 的内部方法";
  private static final String OPT_MGRACTION = "业务实体 '{%1$s}' 中的对外接口方法";
  private static final String OPT_DETERMINATION = "业务实体 '{%1$s}' 中节点 '{%2$s}' 的事件 ";
  private static final String OPT_VALIDATION = "业务实体 '{%1$s}' 中节点 '{%2$s}' 的校验规则 ";
  private static final String EXPRESSION = "业务实体 '{%1$s}' 中节点 '{%2$s}' 的字段 '{%3$s}' ";
  private static final String ASSOCIATION_ENUM = "字段'{%1$s}'的关联带出字段'{%2$s}'的编号和当前节点上字段'{%3$s}'编号相同，请修改当前节点上字段'{%4$s}'的字段编号";
  private static final String TCCSETTINGS = "业务实体 '{%1$s}' 中节点 '{%2$s}'";
  RefCommonService service;

  private RefCommonService getMetadataService() {
    if (service == null) {
      service = SpringBeanUtils.getBean(RefCommonService.class);
    }
    return service;
  }

  private String metaPath;

  /**
   * 业务实体保存前校验
   *
   * @param model 业务实体
   * @param path  当前路径
   */
  public final void validate(GspBusinessEntity model, String path) {
    metaPath = path;
    String validateResult = validateModel(model, path);
    if (validateResult.length() > 0) {
      //保存前校验不通过，抛异常
      throw new BeManagerException("", BE_VALIDATOR_EXCEPTION, validateResult, null,
          ExceptionLevel.Error, false);
    }
  }

  /**
   * 业务实体保存前校验
   *
   * @param model
   * @return 返回报错内容
   */
  private String validateModel(GspBusinessEntity model, String path) {
    ///#region Model
    // 模型基本信息
    String message = validateModelBasicInfo(model, path);
    if (message.length() > 0) {
      return message;
    }
    ///#endregion Model

    ///#region Variables
    message = validateVarableEntity(model);
    if (message.length() > 0) {
      return message;
    }

    ///#endregion

    ///#region Object

    // 所有对象基本信息
    message = validateObjectBasicInfo(model); //1. 编号不能重复
    if (message.length() > 0) {
      return message;
    }

    message = validateBizTags(model);
    if (message.length() > 0) {
      return message;
    }

    // 检查主对象ID字段
    message = validateIDElement(model);
    if (message.length() > 0) {
      return message;
    }

//        // 检查主对象的分级信息
//        message = validateObjectHiberarchyInfo(model);
//        if (message.length() > 0)
//        {
//            return message;
//        }

    // 检查所有子对象的关联关系
    message = validateChildRelation(model);
    if (message.length() > 0) {
      return message;
    }

    // 检查所有子对象的关联关系
    message = validateLogicDeleteElement(model);
    if (message.length() > 0) {
      return message;
    }

    ///#endregion Object

    ///#region Field

    // 检查元素的基本信息
    message = validateElementBasicInfo(model);
    if (message.length() > 0) {
      return message;
    }

    if (model.getIsVirtual() == false) {
      //检查元素的数据类型是否和数据对象的数据类型对应
      message = this.validateElementDataType(model);
      if (message.length() > 0) {
        return message;
      }
    }

    //检查元素的默认值
    message = this.validateElementDefaultValue(model);
    if (message.length() > 0) {
      return message;
    }

    // 同一对象上的元素的LabelID不允许重复
    message = validateElementLabelID(model);
    if (message.length() > 0) {
      return message;
    }

    // 同一对象上的元素的Code不允许重复
    message = validateElementCode(model);
    if (message.length() > 0) {
      return message;
    }

    //字段引用[业务字段]，但是没有配置
    message = validateElementUdt(model);
    if (message.length() > 0) {
      return message;
    }

    ///#endregion Field

    ///#region Operation

    //MgrAction
    message = validateMgrActions(model);
    if (message.length() > 0) {
      return message;
    }

    //obj操作（beAction,validation,determinations）
    message = validateBeActions(model);
    if (message.length() > 0) {
      return message;
    }

    message = validateDeterminations(model);
    if (message.length() > 0) {
      return message;
    }

    message = validateValidations(model);
    if (message.length() > 0) {
      return message;
    }

    message = validateTccSettingCollection(model);
    if (message.length() > 0) {
      return message;
    }

    if (!SpringBeanUtils.getBean(MetadataProjectService.class).isInterpretation(path)) {
      // 关联字段校验。只做生成型
      // 430628 已去掉该校验
      // message = validateAssociateEnum(model);
      if (message.length() > 0) {
        return message;
      }
    }
    ///#endregion Operation

    return "";
  }

  /**
   * 校验be关联枚举字段，不允许有相同编号
   *
   * @param model 业务实体be
   * @return 错误提示
   */
  private String validateAssociateEnum(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    List<IGspCommonObject> allObjectList = model.getAllObjectList();
    for (IGspCommonObject iGspCommonObject : allObjectList) {
      List<IGspCommonElement> elementList = iGspCommonObject.getAllElementList(false);
      // 获取be内枚举字段的编号及名称对应关系
      Map<String, String> elementCodeName = getElementCodeName(elementList);
      if (elementCodeName.isEmpty()) {
        // 无枚举、关联字段，跳过检查
        continue;
      }
      for (IGspCommonElement iGspCommonElement : elementList) {
        if (iGspCommonElement.getObjectType() == GspElementObjectType.Association) {
          List<GspAssociation> elementAssociation = iGspCommonElement.getChildAssociations();
          validateEnum(elementCodeName, elementAssociation, iGspCommonElement.getName(), sb);
        }
      }
    }
    return sb.toString();
  }

  /**
   * 获取枚举、关联字段中编号对应的名称
   *
   * @param elementList be业务实体
   * @return 编号对应名称
   */
  private Map<String, String> getElementCodeName(List<IGspCommonElement> elementList) {
    Map<String, String> elementCodeName = new HashMap<>();
    for (IGspCommonElement iGspCommonElement : elementList) {
      if (iGspCommonElement.getObjectType() == GspElementObjectType.Enum
          || iGspCommonElement.getObjectType() == GspElementObjectType.Association) {
        elementCodeName.put(iGspCommonElement.getCode(), iGspCommonElement.getName());
      }
    }
    return elementCodeName;
  }

  /**
   * 判断关联关系中枚举、关联字段和be中是否存在相同编号
   *
   * @param elementCodeName    编号对应名称
   * @param elementAssociation 关联关系
   * @param eleName            关联字段名称
   * @param sb                 错误提示
   */
  private void validateEnum(Map<String, String> elementCodeName,
      List<GspAssociation> elementAssociation, String eleName, StringBuilder sb) {
    for (GspAssociation gspAssociation : elementAssociation) {
      List<IGspCommonField> refElementList = gspAssociation.getRefElementCollection();
      for (IGspCommonField refElement : refElementList) {
        if (refElement.getObjectType() == GspElementObjectType.Enum
            || refElement.getObjectType() == GspElementObjectType.Association) {
          if (elementCodeName.containsKey(refElement.getCode())) {
            // 存在枚举类型和关联枚举编号相同
            String elementName = elementCodeName.get(refElement.getCode());
            sb.append(String
                .format(ASSOCIATION_ENUM, eleName, refElement.getName(), elementName, elementName));
            sb.append("\n");
          }
        }
      }
    }
  }

  ///#region Model
  // 检查数据模型的基本信息
  private String validateModelBasicInfo(GspBusinessEntity model, String path) {
    StringBuilder sb = new StringBuilder();
    if (CheckInfoUtil.checkNull(model.getCode())) {
      sb.append(String.format(MODEL + "的编号不能为空! ", model.getName()));
    } else {
      // 模型Code限制非法字符
      if (!ConformToNaminGspecification(model.getCode())) {
        sb.append(String
            .format(MODEL + "的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", model.getName()));
        sb.append("\n");
      }
    }
    if (CheckInfoUtil.checkNull(model.getName())) {
      sb.append(String.format(MODEL + "的名称不能为空! ", model.getCode()));
    }

    //todo:[启用时间戳]方案成熟前，先隐藏
    //if (!model.IsUsingTimeStamp)
    //{
    //	// 若传入路径不为空，则检查旧be的值
    //	if (!string.IsNullOrEmpty(path))
    //	{
    //		//旧be中的启用时间戳为true，且已经生成dbo,则不允许设置为false
    //		var service = ServiceManager.GetService<IMetadataService>();
    //		var oldBeMetadata = service.GetRefMetadata(path, model.ID, null);
    //		var oldBe = oldBeMetadata.Content as GspBusinessEntity;
    //		if (oldBe != null && oldBe.IsUsingTimeStamp && !string.IsNullOrEmpty(oldBe.MainObject.RefObjectName))
    //		{
    //			sb.append(String.format("已生成dbo的实体，不允许将[启用时间戳]属性由true改为false。");
    //		}
    //	}
    //}
    if (model.getEnableCaching() && CheckInfoUtil.checkNull(model.getCacheConfiguration())) {
      sb.append(String.format(MODEL + "启用缓存之后，缓存配置不能为空。", model.getName()));
    }
    if (model.getCode().equals(model.getGeneratingAssembly())) {
      sb.append(String.format(MODEL + "编号不可与程序集名相同。", model.getName()));
    }
    if (!CheckInfoUtil.checkNull(model.getVersionContronInfo().getVersionControlElementId())) {

      IGspCommonField ele = model.getMainObject()
          .findElement(model.getVersionContronInfo().getVersionControlElementId());
      if (ele == null) {
        sb.append(String.format(MODEL + "设置的版本字段不存在，请重新设置。", model.getName()));
      } else if (ele.getMDataType() != GspElementDataType.DateTime) {
        sb.append(String
            .format(MODEL + "设置的版本字段应为[日期时间]类型，当前版本字段'{%2$s}'数据类型为'{%3$s}'，请修改。", model.getName(),
                ele.getName(), ele.getMDataType().toString()));
      }
    }
    return sb.toString();
  }

  private String validateVarableEntity(GspCommonModel model) {
    StringBuilder sb = new StringBuilder();
    //validateObjectBasicInfo(model.Variables,sb,model.Name);
    sb.append(validateVariables(model));
    return sb.toString();
  }

  private String validateVariables(GspCommonModel model) {

    CommonVariableCollection vars = model.getVariables().getContainElements();
    StringBuilder sb = new StringBuilder();
    if (vars != null && vars.size() > 0) {

      for (IGspCommonField variable : vars) {
        // 检查元素的基本信息
        validateElementBasicInfo(variable, sb, model.getName(), "变量集合", "变量集合",
            model.getIsVirtual(), VARIABLE);
      }

      // 编号不可重复
      for (int i = 0; i < vars.size() - 1; i++) {
        IGspCommonField firstElement = vars.getItem(i);
        for (int j = i + 1; j < vars.size(); j++) {
          IGspCommonField secondElement = vars.getItem(j);
          if (firstElement.getCode().equals(secondElement.getCode()) && firstElement
              .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
            String message = String
                .format("数据模型 '%1$s' 的'变量集合' 中字段 '%2$s' 和字段 '%3$s' 的 [编号] 属性不允许重复! ",
                    model.getName(), firstElement.getName(), secondElement.getName());
            return message;
          }
        }
      }
    }

    //联动计算
    CommonDtmCollection dtms = new CommonDtmCollection();
    dtms.addAll(model.getVariables().getDtmAfterCreate());
    dtms.addAll(model.getVariables().getDtmAfterModify());
    dtms.addAll(model.getVariables().getDtmBeforeSave());
    sb.append(validateVarDtms(dtms, model.getName()));

    return sb.toString();
  }

  private String validateVarDtms(CommonDtmCollection collection, String modelName) {
    //联动计算
    String errorMessage = String.format(VARIABLE_DTM, modelName);

    List<CommonOperation> dtms = collection.stream().collect(Collectors.toList());
//        ArrayList<CommonDetermination> dtms = collection.getAllItems(item-> {return true;});
    //①必填项
    StringBuilder sb = new StringBuilder();
    sb.append(validateCommonOperationBasicInfo(errorMessage, (ArrayList<CommonOperation>) dtms));
    if (sb.length() > 0) {
      return sb.toString();
    }
    //②编号重复
    sb.append(String.format(
        validateCommonOperationCodeRepeat(errorMessage, (ArrayList<CommonOperation>) dtms)));
    return sb.toString();
  }

  ///#endregion

  ///#region Object

  private void validateObjectBasicInfo(IGspCommonDataType aObject, StringBuilder sb,
      String modelName) {
    if (CheckInfoUtil.checkNull(aObject.getCode())) {
      sb.append(String.format(OBJECT + "的编号不能为空! ", modelName, aObject.getName()));
    } else {
      // 对象Code限制非法字符
      if (!ConformToNaminGspecification(aObject.getCode())) {
        sb.append(String
            .format(OBJECT + "的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", modelName,
                aObject.getName()));
        sb.append("\n");
      }
      // 对象Code限制数据库保留字
      if (!CheckUtil.isLegality(aObject.getCode())) {
        sb.append(String.format(OBJECT + "的 [编号] '{%3$s}'是Java关键字,请修改！ ",
            modelName, aObject.getName(), aObject.getCode()));
        sb.append("\n");
      }
    }
    if (CheckInfoUtil.checkNull(aObject.getName())) {
      sb.append(String.format(OBJECT + "的名称不能为空! ", modelName, aObject.getCode()));
    }
    if (aObject.getCode().length() > 30) {
      sb.append(String.format(OBJECT + "的编号的长度不能超过30! ", modelName, aObject.getName()));
    }
  }

  // 检查数据模型中对象的基本信息
  private String validateObjectBasicInfo(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<IGspCommonObject> aObjectList = model.getAllObjectList();
    for (IGspCommonObject aObject : aObjectList) {
      validateObjectBasicInfo(aObject, sb, model.getName());
    }

    for (IGspCommonObject aObject : aObjectList) {
      for (IGspCommonObject bObject : aObjectList) {
        // 排除本身
        if (aObject.getID().compareTo(bObject.getID()) == 0) {
          continue;
        }

        if (aObject.getID().compareTo(bObject.getCode()) == 0) {
          sb.append(String
              .format(OBJECT + "节点'{%2$s}'的编号相同，请修改。", model.getName(), aObject.getName(),
                  bObject.getName()));
          return sb.toString();
        }
      }
    }

    return sb.toString();
  }

  // 检查主对象ID字段
  private String validateIDElement(GspBusinessEntity model) {
    GspBizEntityObject mObject = model.getMainObject();
    //验证ID字段和Code字段不能有引用和枚举。并且必须必填和插入, 更新必须为false
    GspBizEntityElement idElement =
        (mObject.getIDElement() instanceof GspBizEntityElement) ? mObject.getIDElement() : null;

    StringBuilder sb = new StringBuilder();
    if (idElement.getHasAssociation()) {
      sb.append(String
          .format(FIELD + "作为ID字段, 其 [对象类型] 属性不能为引用类型! ", model.getName(), mObject.getName(),
              idElement.getName()));
      sb.append("\n");
    } else if (idElement.getObjectType() == GspElementObjectType.Enum) {
      sb.append(String
          .format(FIELD + "作为ID字段, 其 [对象类型] 属性不能为枚举类型! ", model.getName(), mObject.getName(),
              idElement.getName()));
      sb.append("\n");
    }
    if (!idElement.getIsRequire()) {
      sb.append(String
          .format(FIELD + "作为ID字段, 其 [是否必须] 属性必须选'是'! ", model.getName(), mObject.getName(),
              idElement.getName()));
      sb.append("\n");
    }
    //ID字段长度及字段数据类型校验
    if (!validateIDElementTypeAndLength(idElement)) {
      sb.append(String.format(FIELD + "作为ID字段, 其字段类型应为[字符串], [长度] 属性应大于36! ", model.getName(),
          mObject.getName(), idElement.getName()));
      sb.append("\n");
    }
    return sb.toString();
  }

  // 模型中的主对象的分级信息
//    private String validateObjectHiberarchyInfo(GspBusinessEntity model)
//    {
//        GspBizEntityObject mObject = model.getMainObject();
//        StringBuilder sb = new StringBuilder();
//        if ((mObject.HirarchyInfo != null && mObject.HirarchyInfo.LayerElement != null && mObject.HirarchyInfo.PathElement != null && mObject.HirarchyInfo.IsDetailElement != null) || (mObject.HirarchyInfo != null && mObject.HirarchyInfo.LayerElement != null && mObject.HirarchyInfo.ParentElement != null && mObject.HirarchyInfo.IsDetailElement != null))
//        {
//            if ((mObject.HirarchyInfo.PathElement != null) && (mObject.HirarchyInfo.LayerElement.ID == mObject.HirarchyInfo.PathElement.ID))
//            {
//                sb.append(String.format(OBJECT + "的 [分级信息] 属性的级数字段与分级码字段不能选择同一字段! ", model.getName(), mObject.getName());
//                sb.append("\n");
//            }
//
//            if ((mObject.HirarchyInfo.ParentElement != null) && (mObject.HirarchyInfo.LayerElement.ID == mObject.HirarchyInfo.ParentElement.ID))
//            {
//                sb.append(String.format(OBJECT + "的 [分级信息] 属性的级数字段与父路径字段不能选择同一字段! ", model.getName(), mObject.getName());
//                sb.append("\n");
//            }
//
//            if (mObject.HirarchyInfo.LayerElement.ID == mObject.HirarchyInfo.IsDetailElement.ID)
//            {
//                sb.append(String.format(OBJECT + "的 [分级信息] 属性的级数字段与是否明细字段不能选择同一字段! ", model.getName(), mObject.getName());
//                sb.append("\n");
//            }
//
//            if ((mObject.HirarchyInfo.PathElement != null) && (mObject.HirarchyInfo.PathElement.ID == mObject.HirarchyInfo.IsDetailElement.ID))
//            {
//                sb.append(String.format(OBJECT + "的 [分级信息] 属性的分级码字段与是否明细字段不能选择同一字段! ", model.getName(), mObject.getName());
//                sb.append("\n");
//            }
//
//            if ((mObject.HirarchyInfo.ParentElement != null) && (mObject.HirarchyInfo.ParentElement.ID == mObject.HirarchyInfo.IsDetailElement.ID))
//            {
//                sb.append(String.format(OBJECT + "的 [分级信息] 属性的父路径字段与是否明细字段不能选择同一字段! ", model.getName(), mObject.getName());
//                sb.append("\n");
//            }
//
//            if (mObject.HirarchyInfo.LayerElement != null && mObject.HirarchyInfo.LayerElement.MDataType != GspElementDataType.Integer)
//            {
//                sb.append(String.format(OBJECT + "的 [分级信息] 属性的级数字段必须为整型! ", model.getName(), mObject.getName());
//            }
//        }
//        return sb.toString();
//    }

  ///#endregion

  ///#region Element

  private String validateElementDefaultValue(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    String regexInt = "^-?\\d+$"; //判断整数，负值也是整数

    Pattern patternInt = Pattern.compile(regexInt);

    java.util.ArrayList<IGspCommonObject> aObjectList = model.getAllObjectList();
    for (IGspCommonObject aObject : aObjectList) {
      java.util.ArrayList<IGspCommonElement> elementList = aObject.getAllElementList(false);
      for (IGspCommonElement ele : elementList) {
        boolean isvalidate = true;
        if (ele.getDefaultValueType() == ElementDefaultVauleType.Expression) {
          validateElementExpression(ele, sb, model.getName(), aObject.getName());
          continue;
        }
        GspElementDataType type = ele.getMDataType();
        String value = ele.getDefaultValue();
        int length = ele.getLength();

        if (!CheckInfoUtil.checkNull(value)) {
          switch (type) {
            case String:
            case Text:
              break;
            case Integer:
              Matcher matcherInt = patternInt.matcher(value);
              isvalidate = matcherInt.matches();
              break;
            case Decimal:
              String reDecimalString = String.format(
                  "^(([0-9]+\\.[0-9]{0,%1$s})|([0-9]*\\.[0-9]{0,%1$s})|([1-9][0-9]+)|([0-9]))$",
                  ele.getPrecision());
              Pattern patternDecimal = Pattern.compile(reDecimalString);
              Matcher matcherDecimal = patternDecimal.matcher(value);
              if (matcherDecimal.matches()) {
                isvalidate = true;
              } else {
                //isvalidate = false;
                sb.append(String.format(FIELD + "的[默认值] 与[数据类型] 不匹配，请检查是否为[浮点数字]，请检查[精度]是否匹配! ",
                    model.getName(), aObject.getName(), ele.getName()));
                sb.append("\n");
                return sb.toString();
              }
              break;
            case Date:
              try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date date = sdf.parse(value);
                isvalidate = true;
              } catch (java.lang.Exception e) {
                isvalidate = false;
              }
              break;
            case DateTime:
              try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = sdf.parse(value);
                isvalidate = true;
              } catch (java.lang.Exception e) {
                isvalidate = false;
              }
              break;
            case Boolean:
              isvalidate = value.equalsIgnoreCase("True") || value
                  .equalsIgnoreCase("False");
              break;
            case Binary:
              isvalidate = value.trim().equals("");
              break;
            default:
              break;
          }
        }
        if (!isvalidate) {
          sb.append(String
              .format(FIELD + "的 [默认值] 与 [数据类型] 不匹配! ", model.getName(), aObject.getName(),
                  ele.getName()));
          sb.append("\n");
        }
      }
    }
    return sb.toString();
  }

  /**
   * 校验be字段表达式类型默认值校验
   *
   * @param ele         be字段
   * @param sb          错误提示
   * @param modelName   工程名称
   * @param aObjectName be名称
   */
  private void validateElementExpression(IGspCommonElement ele, StringBuilder sb, String modelName,
      String aObjectName) {
    String expression = ele.getDefaultValue();
    if (ExpressionVariableCheckUtil.isDateType(expression)) {
      if (ele.getMDataType() == GspElementDataType.Date
          || ele.getMDataType() == GspElementDataType.DateTime) {
        return;
      }
      sb.append(String.format(EXPRESSION + "的数据类型与表达式类型不相符,请选择文本类型的表达式。", modelName, aObjectName,
          ele.getName()));
      sb.append("\n");
    }
    if (ExpressionVariableCheckUtil.isTextType(expression)) {
      if (ele.getMDataType() == GspElementDataType.String
          || ele.getMDataType() == GspElementDataType.Text) {
        return;
      }
      sb.append(String.format(EXPRESSION + "的数据类型与表达式类型不相符,请选择时间类型的表达式。", modelName, aObjectName,
          ele.getName()));
      sb.append("\n");
    }
  }

  private String validateElementLabelID(GspBusinessEntity model) {
    java.util.ArrayList<IGspCommonElement> allElementList = model.getAllElementList(true);

    if (allElementList != null && allElementList.size() > 0) {
      for (int i = 0; i < allElementList.size() - 1; i++) {
        IGspCommonElement firstElement = allElementList.get(i);
        for (int j = i + 1; j < allElementList.size(); j++) {
          IGspCommonElement secondElement = allElementList.get(j);
          if (firstElement.getLabelID().equals(secondElement.getLabelID()) && firstElement
              .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
            String message = String
                .format("数据模型 '%1$s' 的对象 '%2$s' 中字段 '%3$s' 和字段 '%4$s' 的 [标签] 属性不允许重复! ",
                    model.getName(), firstElement.getBelongObject().getName(),
                    firstElement.getName(), secondElement.getName());
            return message;
          }
        }
      }
    }
    return "";
  }

  private String validateElementCode(GspBusinessEntity model) {
    java.util.ArrayList<IGspCommonElement> allElementList = model.getAllElementList(false);
    if (allElementList != null && allElementList.size() > 0) {
      for (int i = 0; i < allElementList.size() - 1; i++) {
        IGspCommonElement firstElement = allElementList.get(i);
        for (int j = i + 1; j < allElementList.size(); j++) {
          IGspCommonElement secondElement = allElementList.get(j);
          if (firstElement.getCode().equals(secondElement.getCode()) && firstElement
              .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
            String message = String
                .format("数据模型 '%1$s' 的对象 '%2$s' 中字段 '%3$s' 和字段 '%4$s' 的 [编号] 属性不允许重复! ",
                    model.getName(), firstElement.getBelongObject().getName(),
                    firstElement.getName(), secondElement.getName());
            return message;
          }
        }
      }
    }
    return "";
  }

  // 关联关系
  private String validateChildRelation(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    GspBizEntityObject mainObject = model.getMainObject();
    if (mainObject != null) {
      for (IGspCommonObject cObject : mainObject.getContainChildObjects()) {
        String message = "";
        if (cObject.getKeys().size() == 0) {
          sb.append(String
              .format(OBJECT + "与父对象 %2$s 缺少关联关系! 请添加! ", model.getName(), cObject.getName(),
                  cObject.getParentObject().getName()));
          sb.append("\n");
        }
        //if (cObject.KeyCollections.Count >= 2)
        //{
        //    sb.append(String.format(OBJECT + "与父对象 '{2}' 存在多关联关系! 目前不支持多关联! ", model.Name, cObject.Name, cObject.ParentObject.Name);
        //    sb.AppendLine();
        //}

        //验证ID字段不能即是主键又是外键
        String cID = cObject.getColumnGenerateID().getElementID();
        GspAssociationKey ak = cObject.getKeys().get(0);
        if (cID.equals(ak.getSourceElement())) {
          sb.append(String
              .format(OBJECT + "与父对象 '{%3$s}' 的关联关系违反外键约束! '{%4$s}' 不能为主键! ", model.getName(),
                  cObject.getName(), cObject.getParentObject().getName(),
                  ak.getSourceElementDisplay()));
          sb.append("\n");
        }

        //ParentID字段应为ID类型
        if (!validateIDElementTypeAndLength(
            cObject.getParentObject().findElement(ak.getSourceElement()))) {
          sb.append(String.format(OBJECT + "与父对象 '{%3$s}' 的关联关系字段{%4$s}不符合ID字段类型，字段类型应为字符串，长度36! ",
              model.getName(), cObject.getName(), cObject.getParentObject().getName(),
              ak.getSourceElementDisplay()));
          sb.append("\n");
        }

        if ((mainObject.getCode().trim().toUpperCase() + "LIST")
            .equals(cObject.getCode().trim().toUpperCase())) {
          sb.append(String
              .format(OBJECT + "的编号不能为 '主对象编号+LIST' 的形式! ", model.getName(), cObject.getName(),
                  cObject.getParentObject().getName(), ak.getSourceElementDisplay()));
          sb.append("\n");
        }

        message = validateChildrenRelation(model, cObject);
        if (message.length() > 0) {
          return message;
        }
      }
    }
    return sb.toString();
  }

  /**
   * 逻辑删除字段
   *
   * @param model
   * @return
   */
  private String validateLogicDeleteElement(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<IGspCommonObject> collection = model.getAllObjectList();

    for (IGspCommonObject cObject : collection) {
      String message = "";
      GspBizEntityObject bizEntityObject = (GspBizEntityObject) cObject;
      LogicDeleteControlInfo info = bizEntityObject.getLogicDeleteControlInfo();
      if (!info.getEnableLogicDelete()) {
        continue;
      }
      String logicDeleteElementId = info.getLogicDeleteControlElementId();
      if (CheckInfoUtil.checkNull(logicDeleteElementId)) {
        sb.append(
            String.format(OBJECT + "中启用删除检查，但是未选择删除检查字段! ", model.getName(), cObject.getName()));
        sb.append("\n");
        continue;
      }

      IGspCommonElement ele = bizEntityObject.findElement(logicDeleteElementId);
      if (ele == null) {
        // 配置，但是字段没了
        sb.append(
            String.format(OBJECT + "中启用删除检查，但是配置的删除检查字段不存在！", model.getName(), cObject.getName()));
        sb.append("\n");
        continue;
      }
      if (ele.getMDataType() != GspElementDataType.Boolean) {
        // 配置，但是字段数据类型错误
        sb.append(String
            .format(OBJECT + "中启用删除检查，但是配置的删除检查字段不是布尔类型！", model.getName(), cObject.getName()));
        sb.append("\n");
        continue;
      }
    }
    return sb.toString();
  }

  /**
   * 校验ID类型字段类型字符串且长度为22 ID字段，ParentID字段，关联字段 TODO:被关联字段暂不考虑
   *
   * @param element
   * @return
   */
  private boolean validateIDElementTypeAndLength(IGspCommonField element) {
    if (element == null) {
      return true;
    }
    return element.getMDataType() == GspElementDataType.String && element.getLength() >= 36;
  }

  private String validateChildrenRelation(GspBusinessEntity model, IGspCommonObject cObject) {
    StringBuilder sb = new StringBuilder();
    if (cObject.getContainChildObjects() != null && cObject.getContainChildObjects().size() > 0) {
      for (int i = 0; i < cObject.getContainChildObjects().size(); i++) {
        IGspCommonObject ccObject = cObject.getContainChildObjects().get(i);
        if (ccObject.getKeys().size() == 0) {
          sb.append(String
              .format(OBJECT + "与父对象 '{2}' 缺少关联关系! 请添加! ", model.getName(), ccObject.getName(),
                  ccObject.getParentObject().getName()));
          sb.append("\n");
        }

        String cID = ccObject.getColumnGenerateID().getElementID();

        GspAssociationKey ak = ccObject.getKeys().get(0);
        if (cID.equals(ak.getSourceElement())) {
          sb.append(String.format(OBJECT + "与父对象 '{2}' 的关联关系违反外键约束! '{3}' 不能为主键! ", model.getName(),
              ccObject.getName(), ccObject.getParentObject().getName(),
              ak.getSourceElementDisplay()));
          sb.append("\n");
        }

        String message = validateChildrenRelation(model, ccObject);
        if (message.length() > 0) {
          sb.append(String.format(message));
          sb.append("\n");
          break;
        }
      }
    }
    return sb.toString();
  }

  private void validateElementBasicInfo(IGspCommonField element, StringBuilder sb, String modelName,
      String objName, String objCode, boolean modelIsVirtual, String errorMessage) {
    if (CheckInfoUtil.checkNull(element.getCode())) {
      sb.append(
          String.format(errorMessage + "的 [编号] 属性不允许为空! ", modelName, objName, element.getName()));
      sb.append("\n");
    } else {
      // 字段Code限制非法字符
      if (!ConformToNaminGspecification(element.getCode())) {
        sb.append(String
            .format(errorMessage + "的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", modelName,
                objName, element.getName()));
        sb.append("\n");
      }
      // 字段Code限制数据库保留字
      else if (isDatabaseReservedWords(element.getCode())) {
        sb.append(String.format(errorMessage + "的 [编号] '%3$s'为数据库保留字，请修改。 ", modelName, objName,
            element.getName(), element.getCode()));
        sb.append("\n");
      }
      // 字段Code限制数据库保留字
      else if (isDatabaseReservedWords(element.getLabelID())) {
        sb.append(String.format(errorMessage + "的 [标签] '%3$s'为数据库保留字，请修改。 ", modelName, objName,
            element.getName(), element.getLabelID()));
        sb.append("\n");
      }
      // 字段Code限制数据库对象保留字（包括1.时间戳字段；2.租户字段TenantID；）
      else if (isDatabaseObjectReservedWords(element.getCode())) {
        sb.append(String
            .format(errorMessage + "的 [编号] '%3$s'为数据库对象保留字（时间戳字段或租户字段TenantID），请修改。 ", modelName,
                objName, element.getName(), element.getCode()));
        sb.append("提示：若希望启用时间戳字段，可在Tab基本信息中，勾选[启用时间戳]。");
        sb.append("\n");
      }
      // 字段LabelID限制数据库对象保留字（包括1.时间戳字段；2.租户字段TenantID；）
      else if (isDatabaseObjectReservedWords(element.getLabelID())) {
        sb.append(String
            .format(errorMessage + "的 [标签] '%3$s'为数据库对象保留字（时间戳字段或租户字段TenantID），请修改。 ", modelName,
                objName, element.getName(), element.getLabelID()));
        sb.append("提示：若希望启用时间戳字段，可在Tab基本信息中，勾选[启用时间戳]。");
        sb.append("\n");
      }
    }
    if (CheckInfoUtil.checkNull(element.getName())) {
      sb.append(
          String.format(errorMessage + "的 [名称] 属性不允许为空! ", modelName, objName, element.getCode()));
      sb.append("\n");
    }

    if (CheckInfoUtil.checkNull(element.getLabelID()) || CheckInfoUtil
        .checkNull(element.getLabelID().trim())) {
      if (modelIsVirtual) {
        element.setLabelID(element.getCode());
      } else {
        sb.append(String
            .format(errorMessage + "的 [标签] 属性不允许为空! ", modelName, objName, element.getName()));
        sb.append("\n");
      }
    } else {
      if (element.getLabelID() == objCode + "_Id") {
        sb.append(String
            .format(errorMessage + "的标签不能是对象的编号+'_Id'。", modelName, objName, element.getName()))
            .append("\r\n");
      }
      if (element.getLabelID().length() > 30) {
        //sb.append(String.format(errorMessage + "的 [标签] 属性的长度不能超过30个字符! ", modelName, objName, element.Name);
        sb.append(String
            .format(errorMessage + "的 [标签] 属性与节点'{%1$s}' [编号]属性的长度和不能超过29，", modelName, objName,
                element.getName()));
        sb.append("\n");
        sb.append(String.format("即“对象编号.字段标签”的长度不能超过30。 "));
        sb.append("\n");
      }

      // LabelID在表单和报表中用作XML的标签，要限制非法字符
      if (!ConformToNaminGspecification(element.getLabelID())) {
        sb.append(String
            .format(errorMessage + "的 [标签] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", modelName,
                objName, element.getName()));
        sb.append("\n");
      } else if (isFrameworkReservedWords(element.getLabelID())) {
        sb.append(String.format(errorMessage + "的 [标签] '{%3$s}'为系统保留字，请修改。", modelName, objName,
            element.getName(), element.getLabelID()));
        sb.append("\n");
      }
    }
    if (element.getObjectType() == GspElementObjectType.Association) {
      //关联字段必须满足ID字段类型
//            if (!validateIDElementTypeAndLength(element)) {
//                sb.append(String.format(errorMessage + "的 [对象类型] 属性为关联, 应满足ID字段类型，字段数据类型为[字符串], 并且[长度]为36! ", modelName, objName, element.getName()));
//                sb.append("\n");
//            }

      if (!element.getHasAssociation()) {
        sb.append(String.format(errorMessage + "的 [对象类型] 属性为关联, [关联] 属性不允许为空! ", modelName, objName,
            element.getName()));
        sb.append("\n");
      } else {
        for (GspAssociation association : element.getChildAssociations()) {
          if (association == null || association.getKeyCollection().size() == 0) {
            sb.append(String
                .format(errorMessage + "的 [对象类型] 属性为关联, [关联] 属性不允许为空! ", modelName, objName,
                    element.getName()));
            sb.append("\n");
          }
          if (StringUtils.isEmpty(association.getRefModelID())) {
            sb.append(String
                .format(errorMessage + "的 [对象类型] 属性为关联, [关联模型] 属性不允许为空! ", modelName, objName,
                    element.getName()));
            sb.append("\n");
          }
          if (StringUtils.isEmpty(association.getRefObjectID())) {
            sb.append(String
                .format(errorMessage + "的 [对象类型] 属性为关联, [关联节点] 属性不允许为空! ", modelName, objName,
                    element.getName()));
            sb.append("\n");
          }
          //处理有时关联字段会丢失的问题
          String sourceElement = "";
          for (GspAssociationKey associationKey : association.getKeyCollection()) {
            if (associationKey.getSourceElement().length() == 0
                || associationKey.getTargetElement().length() == 0) {
              sb.append(
                  String.format(errorMessage + "的引用元素丢失! ", modelName, objName, element.getName()));
              sb.append("\n");
            } else {
              sourceElement = associationKey.getSourceElement();
              String targetElement = associationKey.getTargetElement();
              if (!element.getID().equalsIgnoreCase(targetElement)) {
                sb.append(String
                    .format(errorMessage + "的关联属性[targetElement]值应为当前字段ID! ", modelName, objName,
                        element.getName()));
                sb.append("\n");
              }
            }
          }

          GspMetadata refMetadata = getMetadataService()
              .getRefMetadata(association.getRefModelID());
          if (refMetadata == null) {
            sb.append(
                String.format(errorMessage + "关联的元数据未找到", modelName, objName, element.getName()));
            sb.append("\n");
          } else {
            if (refMetadata.getContent() instanceof GspBusinessEntity) {
              GspBusinessEntity refBusinessEntity = (GspBusinessEntity) refMetadata.getContent();
              IGspCommonObject refObject = refBusinessEntity
                  .findObjectById(association.getRefObjectID());
              if (refObject == null) {
                sb.append(String
                    .format(errorMessage + "关联的节点未找到", modelName, objName, element.getName()));
                sb.append("\n");
              } else {
                if (refObject.findElement(sourceElement) == null) {
                  sb.append(String
                      .format(errorMessage + "关联的字段未找到", modelName, objName, element.getName()));
                  sb.append("\n");
                }
                for (IGspCommonField commonField : association.getRefElementCollection()) {
                  IGspCommonElement refElement = refObject
                      .findElement(commonField.getRefElementId());
                  if (refElement == null) {
                    sb.append(String
                        .format(errorMessage + "带出字段'{%4$s}'在关联模型上未找到", modelName, objName,
                            element.getName(), commonField.getLabelID()));
                    sb.append("\n");
                  }
                }
              }
            }
          }
        }
      }
    } else if (element.getObjectType() == GspElementObjectType.Enum) {
      //todo 暂时屏蔽、后续要加上，前端放开
      // 枚举类型字段，校验默认值为枚举编号
//            if (!CheckInfoUtil.checkNull(element.getDefaultValue()))
//            {
//                String defaultValue = element.getDefaultValue();
//                boolean isEnumKey = false;
//                for (GspEnumValue enumValue : element.getContainEnumValues())
//                {
//                    if (defaultValue.equals(enumValue.getValue()))
//                    {
//                        isEnumKey = true;
//                    }
//                }
//                if (!isEnumKey)
//                {
//                    sb.append(String.format(errorMessage + "的 [对象类型] 属性为枚举, [默认值] 应为枚举编号。 ", modelName,objName, element.getName()));
//                }
//            }
      // 枚举类型字段，非必填
      if (element.getIsRequire()) {
        sb.append(String.format(errorMessage + "的 [对象类型] 属性为枚举, [是否必填] 属性应为否。 ", modelName, objName,
            element.getName()));
        sb.append("\n");
      }

      if (element.getContainEnumValues() == null || element.getContainEnumValues().size() == 0) {
        sb.append(String.format(errorMessage + "的 [对象类型] 属性为枚举, [枚举] 属性不允许为空! ", modelName, objName,
            element.getName()));
        sb.append("\n");
      }

      //处理Enum值必须为string的问题
      for (GspEnumValue ev : element.getContainEnumValues()) {
        String _value = ev.getValue();
        if (element.getMDataType() == GspElementDataType.Boolean) {
          try {
            boolean temp = Boolean.parseBoolean(_value);
          } catch (java.lang.Exception e) {
            sb.append(String
                .format(errorMessage + "的 [枚举] 属性中的枚举值[" + _value + "]应该为布尔值! ", modelName, objName,
                    element.getName()));
            sb.append("\n");
          }
        }
//                else if (element.getMDataType() == GspElementDataType.Integer) {
//                    try {
//                        int temp = Integer.parseInt(ev.getIndex());
//                    } catch (java.lang.Exception e) {
//                        sb.append(String.format(errorMessage + "的 [枚举] 属性中的枚举值["+_value+"]应该为整数! ", modelName, objName, element.getName()));
//                        sb.append("\n");
//                    }
//                }
        else if (element.getMDataType() == GspElementDataType.String) {
          int indexLength = String.valueOf(ev.getIndex()).length();
          int eleLength = element.getLength();
          if (eleLength < indexLength) {
            sb.append(String
                .format(errorMessage + "的 [枚举值]'{%3$s}' 中的索引长度应小于等于字段长度! ", modelName, objName,
                    element.getName(), ev.getName()));
            sb.append("\n");
          }
        }
      }
      if (element.getContainEnumValues() != null && element.getContainEnumValues().size() > 0) {
        for (int i = 0; i < element.getContainEnumValues().size() - 1; i++) {

          GspEnumValue enumValue1 = element.getContainEnumValues().get(i);
          for (int j = i + 1; j < element.getContainEnumValues().size(); j++) {

            GspEnumValue enumValue2 = element.getContainEnumValues().get(j);
            if (enumValue1.getName() == enumValue2.getName()) {
              String message = String
                  .format(errorMessage + "的枚举编号'{0}'重复，重复编号为：【" + enumValue1.getName() + "】",
                      modelName, objName, element.getName(), enumValue1.getName());
              sb.append(message);
              sb.append("\n");
            }
          }
        }
      }
    } else if (element.getObjectType() == GspElementObjectType.DynamicProp) {
      if (element.getDynamicPropSetInfo() != null
          && element.getDynamicPropSetInfo().getDynamicPropSerializerComp() != null && CheckInfoUtil
          .checkNull(element.getDynamicPropSetInfo().getDynamicPropSerializerComp().getId())) {
        sb.append(String
            .format(errorMessage + "的 [序列化构件] 不允许为空! ", modelName, objName, element.getName()));
      }
    }

    if (element.getMDataType() == GspElementDataType.Decimal) {
      if (element.getLength() == 0) {
        sb.append(String.format(errorMessage + "[数据类型] 为[浮点数字]，其 [长度] 不可为0. ", modelName, objName,
            element.getName()));
        sb.append("\n");
      }

      if (element.getPrecision() == 0) {
        sb.append(String.format(errorMessage + "[数据类型] 为[浮点数字]，其 [精度] 不可为0. ", modelName, objName,
            element.getName()));
        sb.append("\n");
      }

    }
    String errorMessageString = String.format(errorMessage, modelName, objName, element.getName());
    if (element.getIsUdt() && CheckInfoUtil.checkNull(element.getUdtID())) {
      sb.append(String
          .format(FIELD + "的数据类型为[业务字段]，请配置其对应的业务字段。", modelName, objName, element.getName()));
      sb.append("\n");
    }
    //20190918盘，临时添加检查：
    //Bug296009,按udtID加载出udt元数据来，看是否为多列的多值udt
    //Bug296448,udt的带出字段包含[普通关联]类型的
    if (element.getObjectType() == GspElementObjectType.Association) {

      for (IGspCommonField refEle : element.getChildAssociations().get(0)
          .getRefElementCollection()) {
        if (refEle.getIsUdt()) {

          String refEleUdtId = refEle.getUdtID();
          if (CheckInfoUtil.checkNull(refEleUdtId)) {
            throw new RuntimeException(
                errorMessageString + "的关联带出字段" + refEle.getLabelID() + "为UDT类型，但其UDTId为空。");
          }

          GspMetadata refEleUdtMeta = getMetadataService().getRefMetadata(refEleUdtId);
          if (refEleUdtMeta == null) {
            throw new RuntimeException(
                errorMessageString + "的关联带出字段" + refEle.getLabelID() + "对应的udt元数据加载失败，udtId="
                    + refEleUdtId);
          }

//                    UnifiedDataTypeDef refUdtContent = (UnifiedDataTypeDef) ((refEleUdtMeta.getContent() instanceof UnifiedDataTypeDef) ? refEleUdtMeta.getContent() : null);
//                    if (refUdtContent instanceof ComplexDataTypeDef) {
//                        if (((ComplexDataTypeDef) refUdtContent).getDbInfo().getMappingType() == ColumnMapType.MultiColumns) {
//                            sb.append(String.format(errorMessageString + "的数据类型为存为多列的多值[业务字段]，暂不支持引用此类关联业务字段。"));
//                            sb.append("\n");
//                        }
//                    }
        }
      }
    }
    // 20191128-N版不支持此种场景，但去掉保存前校验
    //      if (element.IsUdt)
    //{
    //	string udtId = element.UdtID;
    //	var udtMeta= MetadataService.GetRefMetadata(udtId);
    //	if (udtMeta == null)
    //	{
    //		throw new Exception($"{FIELD}对应的udt元数据加载识别，udtId={udtId}。");
    //	}

    //	var udtContent = udtMeta.Content as UnifiedDataTypeDef;
    //	if (udtContent is SimpleDataTypeDef sUdt)
    //	{
    //		if (sUdt.ObjectType == GspElementObjectType.Association)
    //		{
    //			foreach (var refEle in sUdt.ChildAssociations[0].RefElementCollection)
    //			{
    //				if (refEle.ObjectType == GspElementObjectType.Association&&!refEle.IsUdt)
    //				{
    //					sb.append(String.format(FIELD + "的数据类型为关联类型的[业务字段]，且关联带出字段{3}为普通关联类型，暂不支持引用此类关联业务字段。", modelName, objName, element.Name,
    //						refEle.LabelID);
    //					sb.AppendLine();
    //				}
    //			}
    //		}
    //	}
    //}
  }

  //标签唯一性校验
  private String validateBizTags(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<IGspCommonObject> aObjectList = model.getAllObjectList();
    for (IGspCommonObject aObject : aObjectList) {
      List<List<String>> tagLists = aObject.getContainElements().stream()
          .filter(item -> item.getBizTagIds() != null && item.getBizTagIds().size() > 0)
          .map(a -> a.getBizTagIds()).collect(Collectors.toList());
      List<String> tempList = new ArrayList<>();
      if (tagLists != null && tagLists.size() > 0) {
        for (List<String> tag : tagLists) {
          tempList.addAll(tag);
        }
        Map<String, Long> map = tempList.stream()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        for (Map.Entry<String, Long> entry : map.entrySet()) {
          if (entry.getValue() > 1) {
            BizTagService bizTagService = SpringBeanUtils.getBean(BizTagService.class);
            BizTag bizTag = bizTagService.getBizTagById(entry.getKey());
            if (bizTag.isUnique()) {
              return bizTag.getName() + "是唯一性标签，不允许被设置多次";
            }
          }
        }
      }
    }
    return sb.toString();
  }

  //字段
  private String validateElementBasicInfo(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<IGspCommonObject> aObjectList = model.getAllObjectList();
    for (IGspCommonObject aObject : aObjectList) {
      java.util.ArrayList<IGspCommonElement> allElementList = aObject.getAllElementList(false);
      for (IGspCommonElement element : allElementList) {
        validateElementBasicInfo(element, sb, model.getName(), aObject.getName(), aObject.getCode(),
            model.getIsVirtual(), FIELD);
      }
    }
    return sb.toString();
  }

  /**
   * 是否符合命名规范 字母数字下划线组成,字母下划线开头
   *
   * @param text
   * @return
   */
  private boolean ConformToNaminGspecification(String text) {
    String regex = "^[A-Za-z_][A-Za-z_0-9]*$";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(text);
    boolean ismatch = matcher.matches();
    return ismatch;
  }

  //TODO：不校验字段的数据类型转换
  private String validateElementDataType(GspBusinessEntity model) {
    return "";
    //  StringBuilder sb = new StringBuilder();
    //  List<IGspCommonObject> aObjectList = model.GetAllObjectList();
    //  foreach (IGspCommonObject aObject in aObjectList)
    //  {
    //   string tableName = aObject.RefObjectName;
    //   DatabaseObjectTable dtab = ServiceManager.GetService<IDatabaseObjectService>()
    //    .GetDatabaseObject(tableName, DatabaseObjectType.Table) as DatabaseObjectTable;

    //List<IGspCommonElement> elementList = aObject.GetAllElementList(false);
    //   foreach (IGspCommonElement ele in elementList)
    //   {
    //    GspElementDataType type = ele.MDataType;
    //    string baseType = string.Empty;

    //    if (dtab != null && dtab.Columns.Count > 0)
    //    {
    //	    foreach (DatabaseObjectColumn column in dtab.Columns)
    //	    {
    //		    if (ele.ColumnID == column.ID)
    //		    {
    //			    if (!this.CompareDataType(ele, column))
    //			    {
    //				    sb.append(String.format(FIELD + "的 [数据类型] 与数据对象中数据类型不能做匹配转换! ", model.Name, aObject.Name, ele.Name);
    //				    sb.AppendLine();
    //			    }
    //			    break;
    //		    }
    //	    }
    //    }
    //   }
    //  }
    //  return sb.ToString();
  }

  private boolean CompareDataType(IGspCommonElement element, DatabaseObjectColumn column) {
    //TODO: 若已经生成了dbo，需要检查字段类型修改的兼容性
    boolean isRight = true;
    return isRight;
  }

  /**
   * [字段] 校验业务字段相关属性
   *
   * @param model
   * @return
   */

  private String validateElementUdt(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<IGspCommonObject> aObjectList = model.getAllObjectList();
    for (IGspCommonObject aObject : aObjectList) {
      java.util.ArrayList<IGspCommonElement> allElementList = aObject.getAllElementList(false);
      for (IGspCommonElement element : allElementList) {
        GspBizEntityElement bizElement = (GspBizEntityElement) element;
        if (bizElement.getIsUdt() && CheckInfoUtil.checkNull(bizElement.getUdtID())) {
          sb.append(String
              .format(FIELD + "的数据类型为[业务字段]，请配置其对应的业务字段。", model.getName(), aObject.getName(),
                  element.getName()));
          sb.append("\n");
        } else if (bizElement.getIsUdt()) {
          String result = ValudateElementUdt(model, aObject, bizElement);
          if (result.length() > 0) {
            sb.append(result).append("\r\n");
          }
        }
      }
    }
    return sb.toString();
  }

  private String ValudateElementUdt(GspBusinessEntity model, IGspCommonObject aObject,
      GspBizEntityElement bizElement) {
    if (bizElement.getObjectType() != GspElementObjectType.Association) {
      return "";
    }

    GspMetadata udtMetadata = getMetadataService().getRefMetadata(bizElement.getUdtID());
    if (udtMetadata == null) {
      throw new RuntimeException(
          "字段" + bizElement.getLabelID() + "中选中的udt元数据未获取到，udt元数据ID为" + bizElement.getUdtID());
    }
    SimpleDataTypeDef udt =
        (udtMetadata.getContent() instanceof SimpleDataTypeDef) ? udtMetadata.getContent() : null;
    if (!udt.getCode().equals(bizElement.getLabelID())) {
      return "";
    }

    for (IGspCommonField refElement : bizElement.getChildAssociations().get(0)
        .getRefElementCollection()) {
      if (!refElement.getIsFromAssoUdt()) {
        return String.format(FIELD + "的字段标签与所选UDT元数据编号相同时，不允许在be上添加带出字段。", model.getName(),
            aObject.getName(), bizElement.getName());
      }
    }

    return "";
  }

  ///#endregion

  ///#region Operation

  /**
   * [操作]联动计算
   *
   * @param model
   * @return
   */
  private String validateDeterminations(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
//C# TO JAVA CONVERTER TODO TASK: Lambda expressions and anonymous methods are not converted by C# to Java Converter:
    ArrayList<IGspCommonObject> aObjectList = model
        .getAllObjectList();//.stream().collect(item ->item instanceof GspBizEntityObject)
    for (IGspCommonObject aObject : aObjectList) {
      CommonDtmCollection collection = ((GspBizEntityObject) aObject).getBizCommonDtms();
      List<CommonOperation> actions = collection.stream().collect(Collectors.toList());

      String errorMessage = String.format(OPT_DETERMINATION, model.getName(), aObject.getName());
      //①必填项
      sb.append(String.format(
          validateCommonOperationBasicInfo(errorMessage, (ArrayList<CommonOperation>) actions)));
      if (sb.length() > 0) {
        return sb.toString();
      }
      //②编号重复
      sb.append(String.format(
          validateCommonOperationCodeRepeat(errorMessage, (ArrayList<CommonOperation>) actions)));

      //③校验数据状态
//            sb.append(String.format(validateDeterminationSelfProperty(errorMessage, actions)));

      sb.append(String.format(validateDeterminationRequestElements(aObject, errorMessage,
          (ArrayList<CommonOperation>) actions)));
    }
    return sb.toString();
  }

  /**
   * [操作]校验规则
   *
   * @param model
   * @return
   */
  private String validateValidations(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
//C# TO JAVA CONVERTER TODO TASK: Lambda expressions and anonymous methods are not converted by C# to Java Converter:
    java.util.ArrayList<IGspCommonObject> aObjectList = model
        .getAllObjectList();//.stream().m.parallelStream()..ConvertAll(item => (GspBizEntityObject)item);
    for (IGspCommonObject aObject : aObjectList) {
//            java.util.ArrayList<BizOperation> actions = ((GspBizEntityObject) aObject).getValidations();

      CommonValCollection collection = ((GspBizEntityObject) aObject).getBizCommonVals();
      List<CommonOperation> actions = collection.stream().collect(Collectors.toList());
      String errorMessage = String.format(OPT_VALIDATION, model.getName(), aObject.getName());
      //①必填项
      sb.append(String.format(
          validateCommonOperationBasicInfo(errorMessage, (ArrayList<CommonOperation>) actions)));
      if (sb.length() > 0) {
        return sb.toString();
      }
      //②编号重复
      sb.append(String.format(
          validateCommonOperationCodeRepeat(errorMessage, (ArrayList<CommonOperation>) actions)));
      //③触发时机至少选一个
//            sb.append(String.format(validateValidationSelfProperty(errorMessage, actions)));
      sb.append(String.format(validateValidationRequestElements(aObject, errorMessage,
          (ArrayList<CommonOperation>) actions)));
    }
    return sb.toString();
  }

  /**
   * 联动计算至少选择一个数据状态
   *
   * @param errorMessage
   * @param operations
   * @return
   */
  private String validateDeterminationSelfProperty(String errorMessage,
      java.util.ArrayList<BizOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size(); i++) {
        if (operations.get(i) instanceof Determination) {
          Determination dtm = (Determination) operations.get(i);
          if (dtm.getTriggerTimePointType().equals(EnumSet.of(BETriggerTimePointType.AfterModify))
              || dtm.getTriggerTimePointType()
              .equals(EnumSet.of(BETriggerTimePointType.BeforeCheck))) {
            if (dtm.getRequestNodeTriggerType().equals(EnumSet.of(RequestNodeTriggerType.None))) {
              String message = String
                  .format(errorMessage + dtm.getName() + "的 [数据状态] (创建、更新、删除)至少选择一种。");
              sb.append(message);
              sb.append("\n");
            }
          }
        } else {
          throw new BeManagerException("", BE_VALIDATOR_EXCEPTION,
              errorMessage + operations.get(i).getName() + "无法转换为Validation类型。", null,
              ExceptionLevel.Error, false);
        }
      }
    }
    return sb.toString();
  }

  /**
   * 校验触发字段是否存在
   *
   * @param errorMessage
   * @param operations
   * @return
   */
  private String validateDeterminationRequestElements(IGspCommonObject gspCommonObject,
      String errorMessage, java.util.ArrayList<CommonOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size(); i++) {
        if (!(operations.get(i) instanceof BizCommonDetermination)) {
          throw new BeManagerException("", BE_VALIDATOR_EXCEPTION,
              errorMessage + operations.get(i).getName() + "无法转换为Determination类型。", null,
              ExceptionLevel.Error, false);
        }
        BizCommonDetermination dtm = (BizCommonDetermination) operations.get(i);
        com.inspur.edp.cef.designtime.api.collection.DtmElementCollection dtmElementCollection = dtm
            .getRequestElements();
        if (dtmElementCollection != null && dtmElementCollection.size() > 0) {
          for (String element : dtmElementCollection) {
            if (gspCommonObject.findElement(element) == null) {
              String message = errorMessage + dtm.getName() + "的 [触发字段]" + element + "在节点中不存在!";
              sb.append(message);
              sb.append("\n");
            }
          }
        }
        HashMap<String, DtmElementCollection> childDtmElements = dtm.getRequestChildElements();
        if (childDtmElements == null || childDtmElements.size() == 0) {
          continue;
        }
        for (Map.Entry<String, DtmElementCollection> entry : childDtmElements.entrySet()) {
          String key = entry.getKey();
          DtmElementCollection value = entry.getValue();
          IObjectCollection childObjects = gspCommonObject.getContainChildObjects();
          if (childObjects == null || childObjects.size() == 0) {
            String message = errorMessage + dtm.getName() + "的 触发字段对应子节点" + key + "在在节点中不存在!";
            sb.append(message);
            sb.append("\n");
            continue;
          }
          IGspCommonObject reqChildObj = null;
          for (IGspCommonObject childObj : childObjects) {
            if (childObj.getID().equals(key)) {
              reqChildObj = childObj;
              break;
            }
          }
          if (reqChildObj == null) {
            String message = errorMessage + dtm.getName() + "的 触发字段对应子节点" + key + "在子节点中不存在!";
            sb.append(message);
            sb.append("\n");
            continue;
          }
          if (value == null || value.getCount() == 0) {
            String message = errorMessage + dtm.getName() + "的 触发字段对应子节点" + key + "未设置触发字段!";
            sb.append(message);
            sb.append("\n");
            continue;
          }
          for (String childElement : value) {
            if (reqChildObj.findElement(childElement) == null) {
              String message =
                  errorMessage + dtm.getName() + "的 触发字段" + childElement + "在字段列表中不存在!";
              sb.append(message);
              sb.append("\n");
            }
          }
        }
      }
    }
    return sb.toString();
  }

  private String validateValidationRequestElements(IGspCommonObject gspCommonObject,
      String errorMessage, java.util.ArrayList<CommonOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size(); i++) {
        if (!(operations.get(i) instanceof CommonValidation)) {
          throw new BeManagerException("", BE_VALIDATOR_EXCEPTION,
              errorMessage + operations.get(i).getName() + "无法转换为Validation类型。", null,
              ExceptionLevel.Error, false);
        }
        BizCommonValdation val = (BizCommonValdation) operations.get(i);
        ValElementCollection valElementCollection = val.getRequestElements();
        if (valElementCollection != null && valElementCollection.size() > 0) {
          for (String element : valElementCollection) {
            if (gspCommonObject.findElement(element) == null) {
              String message = errorMessage + val.getName() + "的 [触发字段]" + element + "在节点中不存在!";
              sb.append(message);
              sb.append("\n");
            }
          }
        }
        HashMap<String, ValElementCollection> childValElements = val.getRequestChildElements();
        if (childValElements == null || childValElements.size() == 0) {
          continue;
        }
        for (Map.Entry<String, ValElementCollection> entry : childValElements.entrySet()) {
          String key = entry.getKey();
          ValElementCollection value = entry.getValue();
          IObjectCollection childObjects = gspCommonObject.getContainChildObjects();
          if (childObjects == null || childObjects.size() == 0) {
            String message = errorMessage + val.getName() + "的 触发字段对应子节点" + key + "在在节点中不存在!";
            sb.append(message);
            sb.append("\n");
            continue;
          }
          IGspCommonObject reqChildObj = null;
          for (IGspCommonObject childObj : childObjects) {
            if (childObj.getID().equals(key)) {
              reqChildObj = childObj;
              break;
            }
          }
          if (reqChildObj == null) {
            String message = errorMessage + val.getName() + "的 触发字段对应子节点" + key + "在子节点中不存在!";
            sb.append(message);
            sb.append("\n");
            continue;
          }
          if (value == null || value.getCount() == 0) {
            String message = errorMessage + val.getName() + "的 触发字段对应子节点" + key + "未设置触发字段!";
            sb.append(message);
            sb.append("\n");
            continue;
          }
          for (String childElement : value) {
            if (reqChildObj.findElement(childElement) == null) {
              String message =
                  errorMessage + val.getName() + "的 触发字段" + childElement + "在字段列表中不存在!";
              sb.append(message);
              sb.append("\n");
            }
          }
        }
      }
    }
    return sb.toString();
  }

  /**
   * 校验规则至少选择一个执行时机/一个数据状态
   *
   * @param errorMessage
   * @param operations
   * @return
   */
  private String validateValidationSelfProperty(String errorMessage,
      java.util.ArrayList<BizOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size(); i++) {
        if (operations.get(i) instanceof Validation) {
          Validation val = (Validation) operations.get(i);
          if (val.getValidationTriggerPoints() == null
              || val.getValidationTriggerPoints().size() == 0) {
            String message = String.format(errorMessage + val.getName() + "的 [执行时机] 至少选择一种。");
            sb.append(message);
            sb.append("\n");
          } else {
            boolean hasTimePoint = false;

            for (Map.Entry<BETriggerTimePointType, EnumSet<RequestNodeTriggerType>> point : val
                .getValidationTriggerPoints().entrySet()) {
              if (!(point.getValue().equals(EnumSet.of(RequestNodeTriggerType.None)))) {
                hasTimePoint = true;
              }
            }
            if (!hasTimePoint) {
              String message = String.format(errorMessage + val.getName() + "的 [执行时机] 至少选择一种。");
              sb.append(message);
              sb.append("\n");
            }
          }

          //if (val.TriggerTimePointType ==BETriggerTimePointType.None)
          //{
          //	string message = string.Format(errorMessage + $"'{val.Name}'的 [执行时机] 至少选择一种。");
          //	sb.Append(message);
          //	sb.AppendLine();
          //}

          //if (val.RequestNodeTriggerType ==RequestNodeTriggerType.None)
          //{
          //	string message = string.Format(errorMessage + $"'{val.Name}'的 [数据状态] 至少选择一种。");
          //	sb.Append(message);
          //	sb.AppendLine();
          //}
        } else {
          throw new BeManagerException("", BE_VALIDATOR_EXCEPTION,
              errorMessage + operations.get(i).getName() + "无法转换为Validation类型。", null,
              ExceptionLevel.Error, false);
        }
      }
    }
    return sb.toString();
  }

  /**
   * [操作]业务实体动作
   *
   * @param model
   * @return
   */
  private String validateBeActions(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
//C# TO JAVA CONVERTER TODO TASK: Lambda expressions and anonymous methods are not converted by C# to Java Converter:
    ArrayList<IGspCommonObject> aObjectList = model
        .getAllObjectList();//.ConvertAll(item => (GspBizEntityObject)item);
    for (IGspCommonObject aObject : aObjectList) {
      java.util.ArrayList<BizOperation> actions = ((GspBizEntityObject) aObject).getBizActions();

      String errorMessage = String.format(OPT_BIZACTION, model.getName(), aObject.getName());
      //①必填项
      sb.append(String.format(validateOperationBasicInfo(errorMessage, actions)));
      if (sb.length() > 0) {
        return sb.toString();
      }
      //②编号重复
      sb.append(String.format(validateOperationCodeRepeat(errorMessage, actions)));
      if (sb.length() > 0) {
        return sb.toString();
      }
      //③参数及返回值校验
      sb.append(String.format(validateActionParas(errorMessage, actions)));
    }
    return sb.toString();
  }

  /**
   * [操作]自定义动作
   *
   * @param model
   * @return
   */
  private String validateMgrActions(GspBusinessEntity model) {
    String errorMessage = String.format(OPT_MGRACTION, model.getName());
    StringBuilder sb = new StringBuilder();
    java.util.ArrayList<BizOperation> actions = model.getBizMgrActions();
    //①必填项
    sb.append(String.format(validateOperationBasicInfo(errorMessage, actions)));
    if (sb.length() > 0) {
      return sb.toString();
    }
    //②编号重复
    sb.append(String.format(validateOperationCodeRepeat(errorMessage, actions)));
    if (sb.length() > 0) {
      return sb.toString();
    }
    //③参数及返回值校验
    sb.append(String.format(validateActionParas(errorMessage, actions)));
    return sb.toString();
  }

  /**
   * [操作]编号重复
   *
   * @param errorMessage
   * @param operations
   * @return
   */
  private String validateOperationCodeRepeat(String errorMessage,
      java.util.ArrayList<BizOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size() - 1; i++) {
        BizOperation firstOperation = operations.get(i);
        for (int j = i + 1; j < operations.size(); j++) {
          BizOperation secondOperation = operations.get(j);
          if (firstOperation.getCode().equals(secondOperation.getCode())) {
            String message = String.format(
                errorMessage + "'{%1$s}'与'{%2$s}'的编号重复，重复编号为：【" + firstOperation.getCode() + "】",
                firstOperation.getName(), secondOperation.getName());
            sb.append("\n");
            return message;
          }
        }
      }
    }
    return sb.toString();
  }

  /**
   * [操作]编号名称为空
   *
   * @param errorMessage
   * @param oprs
   * @return
   */
  private String validateOperationBasicInfo(String errorMessage,
      java.util.ArrayList<BizOperation> oprs) {
    if (oprs == null || oprs.isEmpty()) {
      return "";
    }
    StringBuilder sb = new StringBuilder();

    for (BizOperation opr : oprs) {
      if (CheckInfoUtil.checkNull(opr.getID())) {
        opr.setID(UUID.randomUUID().toString());
        //sb.append(String.format(errorMessage + string.Format("'{0}'的 [ID] 属性不允许为空! ", opr.Name));
        //sb.AppendLine();
      }
      if (CheckInfoUtil.checkNull(opr.getCode())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [编号] 属性不允许为空! ", opr.getName())));
        sb.append("\n");
      } else {
        // 操作Code限制非法字符
        if (!ConformToNaminGspecification(opr.getCode())) {
          sb.append(String.format(errorMessage + String
              .format("'%1$s'的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", opr.getName())));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(opr.getName())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [名称] 属性不允许为空! ", opr.getCode())));
        sb.append("\n");
      }
    }
    return sb.toString();
  }


  /**
   * [操作]编号重复
   *
   * @param errorMessage
   * @param operations
   * @return
   */
  private String validateCommonOperationCodeRepeat(String errorMessage,
      java.util.ArrayList<CommonOperation> operations) {
    StringBuilder sb = new StringBuilder();
    if (operations != null && operations.size() > 0) {
      for (int i = 0; i < operations.size() - 1; i++) {

        CommonOperation firstOperation = operations.get(i);
        for (int j = i + 1; j < operations.size(); j++) {

          CommonOperation secondOperation = operations.get(j);
          if (firstOperation.getCode().equals(secondOperation.getCode())) {
            String message = String
                .format(errorMessage + "%1$s与%2$s的编号重复，重复编号为：【" + firstOperation.getCode() + "】",
                    firstOperation.getName(), secondOperation.getName());
            sb.append("\n");
            return message;
          }
        }
      }
    }
    return sb.toString();
  }

  /**
   * [操作]编号名称为空
   *
   * @param errorMessage
   * @param oprs
   * @return
   */
  private String validateCommonOperationBasicInfo(String errorMessage,
      java.util.ArrayList<CommonOperation> oprs) {
    if (oprs == null || oprs.isEmpty()) {
      return "";
    }
    StringBuilder sb = new StringBuilder();

    for (CommonOperation opr : oprs) {
      if (CheckInfoUtil.checkNull(opr.getID())) {
        opr.setID(UUID.randomUUID().toString());
        //sb.append(String.format(errorMessage + string.Format("'{0}'的 [ID] 属性不允许为空! ", opr.Name));
        //sb.AppendLine();
      }
      if (CheckInfoUtil.checkNull(opr.getCode())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [编号] 属性不允许为空! ", opr.getName())));
        sb.append("\n");
      } else {
        // 操作Code限制非法字符
        if (!ConformToNaminGspecification(opr.getCode())) {
          sb.append(String.format(errorMessage + String
              .format("'%1$s'的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ", opr.getName())));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(opr.getName())) {
        sb.append(
            String.format(errorMessage + String.format("'%1$s'的 [名称] 属性不允许为空! ", opr.getCode())));
        sb.append("\n");
      }
    }
    return sb.toString();
  }

  /**
   * [操作]-action-参数
   *
   * @param opr
   * @param errorMessage
   * @return
   */
  private String validateActionReturnValue(BizActionBase opr, String errorMessage) {
    StringBuilder sb = new StringBuilder();
    BizReturnValue returnValue = opr.getReturnValue();
    if (returnValue != null && returnValue.getParameterType() == BizParameterType.Custom) {
      if (BeManagerService.CreatJavaModule(metaPath)) {
        if (opr.getIsGenerateComponent() && CheckInfoUtil.checkNull(returnValue.getClassName())) {
          sb.append(String
              .format("J版元数据工程，" + errorMessage + "'%1$s'中的返回值的 [类型] 为自定义类型，请完善其Java类名。",
                  opr.getName()));
          sb.append("\n");
        }
      }
    }
    return sb.toString();
  }


  /**
   * 校验动作参数及返回值
   *
   * @param errorMessage
   * @param actions
   * @return
   */
  private String validateActionParas(String errorMessage,
      java.util.ArrayList<BizOperation> actions) {
    StringBuilder sb = new StringBuilder();
    if (actions != null && actions.size() > 0) {

      for (BizOperation action : actions) {
        sb.append(String.format(validateActionParas((BizActionBase) action, errorMessage)));
        sb.append(String.format(validateActionComponent((BizActionBase) action, errorMessage)));
        sb.append(String.format(validateActionReturnValue((BizActionBase) action, errorMessage)));
      }
    }
    return sb.toString();
  }

  private String validateActionParas(BizActionBase opr, String message) {
    StringBuilder sb = new StringBuilder();
    //参数编号名称不可为空

    for (Object para : opr.getParameters()) {
      if (CheckInfoUtil.checkNull(((IBizParameter) para).getParamCode())) {
        sb.append(String.format(message + String
            .format("'%1$s'中的参数'%2$s'的 [编号] 属性不允许为空! ", opr.getName(),
                ((IBizParameter) para).getParamName())));
        sb.append("\n");
      } else {
        // 参数编号Code限制非法字符
        if (!ConformToNaminGspecification(((IBizParameter) para).getParamCode())) {
          sb.append(String.format(message + String
              .format("'%1$s'中的参数'%2$s'的 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ",
                  opr.getName(), ((IBizParameter) para).getParamName())));
          sb.append("\n");
        }
      }
      if (CheckInfoUtil.checkNull(((IBizParameter) para).getParamName())) {
        sb.append(String.format(message + String
            .format("'%1$s'中的参数'%2$s'的 [名称] 属性不允许为空! ", opr.getCode(),
                ((IBizParameter) para).getParamCode())));
        sb.append("\n");
      }
      if (((IBizParameter) para).getParameterType() == BizParameterType.Custom) {
        if (BeManagerService.CreatJavaModule(metaPath)) {
          if (opr.getIsGenerateComponent() && CheckInfoUtil
              .checkNull(((IBizParameter) para).getClassName())) {
            sb.append(String
                .format("J版元数据工程，" + message + "'%1$s'中的参数'%2$s' [参数类型] 为自定义类型，请完善其Java类名。",
                    opr.getName(), ((IBizParameter) para).getParamName()));
            sb.append("\n");
          }
        }
      }
    }
    if (sb.length() > 0) {
      return sb.toString();
    }

    //参数编号不可重复
    if (opr.getParameters() != null && opr.getParameters().getCount() > 0) {
      for (int i = 0; i < opr.getParameters().getCount() - 1; i++) {
        IBizParameter firstPara = opr.getParameters().getItem(i);
        for (int j = i + 1; j < opr.getParameters().getCount(); j++) {
          IBizParameter secondPara = opr.getParameters().getItem(j);
          if (firstPara.getParamCode().equals(secondPara.getParamCode())) {
            sb.append(String.format(
                message + "'{%1$s}'中的参数'{%2$s}'和参数'{%3$s}'的[编号] 属性不允许重复,重复编号为：【" + firstPara
                    .getParamCode() + "】", opr.getName(), firstPara.getParamName(),
                secondPara.getParamName()));
            sb.append("\n");
          }
        }
      }
    }
    return sb.toString();
  }


  private String validateActionComponent(BizActionBase opr, String message) {
    //内置实体动作和自定义动作不用校验
    if (opr instanceof IInternalMgrAction || opr instanceof IInternalBEAction) {
      return "";
    }
    StringBuilder sb = new StringBuilder();
    //参数编号名称不可为空
    ICompParameterCollection compParameterCollection = null;
    if (!opr.getIsGenerateComponent() && StringUtils.isEmpty(opr.getComponentId())) {
      sb.append(String.format(message + String.format("'%1$s'中构件ID 属性不允许为空! ", opr.getName())));
      sb.append("\n");
      return sb.toString();
    }
    //新增的时候，构件ID是空的
    if (StringUtils.isEmpty(opr.getComponentId())) {
      return sb.toString();
    }
    RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);
    GspMetadata metadata = metadataService.getRefMetadata(opr.getComponentId());
    if (metadata == null) {
      sb.append(String.format(message + String.format("'%1$s'对应的构件元数据不存在!", opr.getName())));
      sb.append("\n");
      return sb.toString();
    }
    if (metadata.getContent() instanceof GspComponent) {
      if (!opr.getIsGenerateComponent()) {
        GspComponent component = (GspComponent) metadata.getContent();
        compParameterCollection = component.getMethod().getCompParameters();
        int oprParSize = opr.getParameters() == null ? 0 : opr.getParameters().getCount();
        int compParSize = compParameterCollection == null ? 0 : compParameterCollection.getCount();
        if (oprParSize != compParSize) {
          sb.append(String.format(message + String
              .format("'%1$s'的参数个数为:%2$s,构件上参数个数:%3$s!", opr.getName(), oprParSize, compParSize)));
          sb.append("\n");
          return sb.toString();
        }
      }
    }
    if (!opr.getIsGenerateComponent()) {
      for (int i = 0; i < opr.getParameters().getCount(); i++) {
        IBizParameter bizParameter = opr.getParameters().getItem(i);
        ICompParameter compParameter = compParameterCollection.getItem(i);
        //引用构件的才校验
        sb.append(validBizCompParameter(bizParameter, compParameter, opr, message));
      }
    }

    if (sb.length() > 0) {
      return sb.toString();
    }

    //参数编号不可重复
    if (opr.getParameters() != null && opr.getParameters().getCount() > 0) {
      for (int i = 0; i < opr.getParameters().getCount() - 1; i++) {
        IBizParameter firstPara = opr.getParameters().getItem(i);
        for (int j = i + 1; j < opr.getParameters().getCount(); j++) {
          IBizParameter secondPara = opr.getParameters().getItem(j);
          if (firstPara.getParamCode().equals(secondPara.getParamCode())) {
            sb.append(String.format(
                message + "'{0}'中的参数'{1}'和参数'{2}'的[编号] 属性不允许重复,重复编号为：【" + firstPara.getParamCode()
                    + "】", opr.getName(), firstPara.getParamName(), secondPara.getParamName()));
            sb.append("\n");
          }
        }
      }
    }
    return sb.toString();
  }

  private String validBizCompParameter(IBizParameter bizParameter, ICompParameter compParameter,
      BizActionBase bizActionBase, String message) {
    StringBuilder sb = new StringBuilder();
    if (!bizParameter.getParamCode().equalsIgnoreCase(compParameter.getParamCode())) {
      sb.append(String
          .format(message + "'%1$s'中的参数'%2$s'和构件参数'%3$s'的[编号] 属性不一致", bizActionBase.getName(),
              bizParameter.getParamCode(), compParameter.getParamCode()));
    }
    //老的BE存在为空的情况
//        if(!bizParameter.getClassName().equalsIgnoreCase(compParameter.getClassName())){
//            sb.append(String.format(message + "'%1$s'中的参数'%2$s'和构件参数的[类型] 属性不一致，类型分别为'%3$s','%4$s'", bizActionBase.getName(), bizParameter.getParamCode(),bizParameter.getClassName(), compParameter.getClassName()));
//        }
    return sb.toString();
  }

  /**
   * [操作]业务实体动作
   *
   * @param model * @return
   */
  private String validateTccSettingCollection(GspBusinessEntity model) {
    StringBuilder sb = new StringBuilder();
    ArrayList<IGspCommonObject> objectList = model.getAllObjectList();
    for (IGspCommonObject object : objectList) {
      String errorMessage = String.format(TCCSETTINGS, model.getName(), object.getName());
      TccSettingCollection settings = ((GspBizEntityObject) object).getTccSettings();
      // ①TCC配置字段校验
      for (TccSettingElement ele : settings) {
        sb.append(validateTccElement(errorMessage, ele));
      }
      // ②TCC字段Code重复性校验
      String repeatMessage = validateTccSettingCollectionCodeRepeat(errorMessage,
          ((GspBizEntityObject) object).getTccSettings());
      if (!StringUtils.isEmpty(repeatMessage)) {
        sb.append(validateTccSettingCollectionCodeRepeat(errorMessage,
            ((GspBizEntityObject) object).getTccSettings()));
      }
    }
    return sb.toString();
  }

  private String validateTccElement(String errorMessage, TccSettingElement element) {
    StringBuilder sb = new StringBuilder();
    if (CheckInfoUtil.checkNull(element.getCode())) {
      sb.append(String.format(errorMessage + "的TCC配置字段的 [编号] 属性不允许为空! ", element.getName()));
      sb.append("\n");
    } else {
      // 字段Code限制非法字符
      if (!ConformToNaminGspecification(element.getCode())) {
        sb.append(String
            .format(errorMessage + "的TCC配置字段 [编号] 属性必须以英文字母或下划线开头, 并且只能由英文字母、数字、下划线(_)组成! ",
                element.getName()));
        sb.append("\n");
      }
      // 字段Code限制数据库保留字
      else if (isDatabaseReservedWords(element.getCode())) {
        sb.append(String.format(errorMessage + "的 [编号] '%3$s'为数据库保留字，请修改。 ", element.getName(),
            element.getCode()));
        sb.append("\n");
      } else if (isDatabaseObjectReservedWords(element.getCode())) {
        sb.append(String.format(errorMessage + "的 [编号] '%3$s'为数据库对象保留字（时间戳字段或租户字段TenantID），请修改。 ",
            element.getName(), element.getCode()));
        sb.append("\n");
      }
    }
    if (CheckInfoUtil.checkNull(element.getName())) {
      sb.append(String.format(errorMessage + "的 [名称] 属性不允许为空! ", element.getCode()));
      sb.append("\n");
    }

    String validateTccAtionResult = validateTccAction(errorMessage, element);
    if (!CheckInfoUtil.checkNull(validateTccAtionResult)) {
      sb.append(validateTccAtionResult);
    }
    return sb.toString();
  }

  private String validateTccAction(String errorMessage, TccSettingElement element) {
    ArrayList<BizOperation> actions = new ArrayList<>();
    actions.add(element.getTccAction());
    return validateOperationBasicInfo(errorMessage, actions);
  }

  private String validateTccSettingCollectionCodeRepeat(String errorMessage,
      TccSettingCollection collection) {
    if (collection != null && collection.size() > 0) {
      for (int i = 0; i < collection.size() - 1; i++) {
        TccSettingElement firstEle = collection.get(i);
        for (int j = i + 1; j < collection.size(); j++) {
          TccSettingElement secondEle = collection.get(j);
          if (firstEle.getCode().equals(secondEle.getCode())) {
            String message = String
                .format(errorMessage + "%1$s与%2$s的编号重复，重复编号为：【" + firstEle.getCode() + "】",
                    firstEle.getName(), secondEle.getName());
            return message;
          }
        }
      }
    }
    return null;
  }
  ///#endregion

  ///#region Util

  private boolean isDatabaseReservedWords(String word) {
    return DatabaseReservedWords.isReservedWord(word);
  }

  private boolean isDatabaseObjectReservedWords(String word) {
    //todo:[启用时间戳]方案成熟前，先隐藏
    //return DatabaseObjectReservedWords.IsReservedWord(word);
    return false;
  }

  private static final java.util.ArrayList<String> fwkReserveds = new java.util.ArrayList<String>(
      java.util.Arrays.asList("DynamicPropSet"));

  private static boolean isFrameworkReservedWords(String word) {
    return fwkReserveds.contains(word);
  }

  ///#endregion
}
